//
//  DMCircleScrollView.m
//  DMCollectionView
//
//  Created by Apple on 2017/7/5.
//  Copyright © 2017年 Xwg. All rights reserved.
//

#import "DMCircleScrollView.h"

#define kMultiple 1000           // 倍数

@interface DMCircleScrollView () <UICollectionViewDataSource, UICollectionViewDelegate>
@property (nonatomic, strong) UICollectionViewFlowLayout *layout;
@property (nonatomic, strong) UICollectionView *collectionView;

/** 保存重用标识, 不可以修改 */
@property (nonatomic, copy) NSString *ID;
@end
@implementation DMCircleScrollView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self initSetup];
    }
    return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    if (self) {
        [self initSetup];
    }
    return self;
}

- (void)initSetup {
    [self addSubview:self.collectionView];
}

- (void)setNumberOfItems:(NSInteger)numberOfItems {
    _numberOfItems = numberOfItems < 0 ? 0 : numberOfItems;
    
    // 刷新数据
    [self.collectionView reloadData];
    
    // 滚动到中间
    if (self.numberOfItems != 0) {
        [self scrollToDefaultPosition];
    }
}
- (void)setFrame:(CGRect)frame {
    [super setFrame:frame];
    // 设置collectionView
    self.collectionView.frame = self.bounds;
    // 设置layout
    [self setupItemSize];
}


/**
 设置item的宽度

 @param itemWidth item的宽度
 */
- (void)setItemWidth:(CGFloat)itemWidth {
    _itemWidth = itemWidth > 0 ? itemWidth : 0;
    [self setupItemSize];
}


/**
 设置item的宽高比

 @param itemAspectRatio 宽高比
 */
- (void)setItemAspectRatio:(CGFloat)itemAspectRatio {
    _itemAspectRatio = itemAspectRatio > 0 ? itemAspectRatio : 0;
    [self setupItemSize];
}

/**
 设置item的间距

 @param itemSpacing 间距
 */
- (void)setItemSpacing:(CGFloat)itemSpacing {
    _itemSpacing = itemSpacing;
    self.layout.minimumLineSpacing = itemSpacing;
}

- (void)setupItemSize {
    
    CGFloat itemH = self.frame.size.height;
    // 未设置self的高度为0
    if (itemH == 0) return;
    // 计算item的宽度（优先使用itemWidth）
    CGFloat itemW = self.itemWidth > 0 ? self.itemWidth : itemH * self.itemAspectRatio;
    if (itemW == 0) return;
    
    // 设置item的大小
    self.layout.itemSize = CGSizeMake(itemW, itemH);
    
    // 赋值 (注：不可以用点方法来调用属性，会执行setting方法，造成死循环)
    _itemWidth = itemW;
    _itemAspectRatio = itemW / itemH;
}

#pragma mark - 懒加载
- (UICollectionViewFlowLayout *)layout {
    if (!_layout) {
        _layout = [[UICollectionViewFlowLayout alloc] init];
        _layout.minimumLineSpacing = 10;
        _layout.minimumInteritemSpacing = 0.0;
        _layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    }
    return _layout;
}
- (UICollectionView *)collectionView {
    if (!_collectionView) {
        _collectionView = [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:self.layout];
        _collectionView.dataSource = self;
        _collectionView.delegate = self;
        _collectionView.pagingEnabled = NO;
        _collectionView.decelerationRate = UIScrollViewDecelerationRateFast;
        _collectionView.showsHorizontalScrollIndicator = NO;
        _collectionView.showsVerticalScrollIndicator = NO;
        _collectionView.backgroundColor = [UIColor clearColor];
    }
    return _collectionView;
}

#pragma mark - 注册item
- (void)registerWithClass:(Class)cellClass forCellWithReuseIdentifier:(NSString *)ID {
    self.ID = ID;
    [self.collectionView registerClass:cellClass forCellWithReuseIdentifier:ID];
}
- (void)registerWithNib:(UINib *)cellNib forCellWithReuseIdentifier:(NSString *)ID {
    
    self.ID = ID;
    [self.collectionView registerNib:cellNib forCellWithReuseIdentifier:ID];
}

#pragma mark - UICollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return self.numberOfItems * kMultiple;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    // 取出cell
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:self.ID forIndexPath:indexPath];
    // 设置cell
    if (self.setupCellForItemAtIndex) self.setupCellForItemAtIndex(cell, indexPath.item ,[self indexAtItemPath:indexPath]);
    // 返回cell
    return cell;
}

#pragma mark - UICollectionViewDelegate
// 用户点击
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    if (self.didSelectItem) self.didSelectItem(indexPath.item , [self indexAtItemPath:indexPath]);
}



#pragma mark - UISCrollViewDelegate

/**
 人为手动结束
 */
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    // 类型转换
    UICollectionView *cv = (UICollectionView *)scrollView;
    UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)cv.collectionViewLayout;
    
    // 当前屏幕所对应scrollView中的位置
    CGRect currentFrame = CGRectMake(scrollView.contentOffset.x,
                                     0,
                                     scrollView.frame.size.width,
                                     scrollView.frame.size.height);
    // 取出当前屏幕中第一个item对应的属性
    UICollectionViewLayoutAttributes *firstAtrrs = [layout layoutAttributesForElementsInRect:currentFrame].firstObject;
    // 如果不存在，则直接返回
    if (!firstAtrrs) return;
    
    // 默认对应位置 = 默认位置 + 偏移
    CGFloat offsetX = [self defaultPositionXWithItem:firstAtrrs.indexPath.item] + (scrollView.contentOffset.x - CGRectGetMinX(firstAtrrs.frame));
    
    // 恢复到默认位置
    [scrollView setContentOffset:CGPointMake(offsetX, 0) animated:NO];
}

/**
 拖动后将滚动的位置
 
 @param scrollView scrollView
 @param velocity 是滚动速率  有个x和y 如果x有值 说明x上有速度
 @param targetContentOffset 最终滚动到的contentOffset
 */
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
    UICollectionView *cv = (UICollectionView *)scrollView;
    UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)cv.collectionViewLayout;
    
    // 当前屏幕所对应scrollView中的位置
    CGRect currentFrame = CGRectMake(targetContentOffset->x,
                                     0,
                                     scrollView.frame.size.width,
                                     scrollView.frame.size.height);
    
    // 取出当前屏幕中所有的item对应的属性
    NSArray<UICollectionViewLayoutAttributes *> *layoutAttrsArr = [layout layoutAttributesForElementsInRect:currentFrame];
    if (layoutAttrsArr.count == 0) return;
    
    // 计算出目标中点
    CGFloat centerX = targetContentOffset->x + CGRectGetWidth(scrollView.frame) * 0.5;
    
    // 计算哪个item的中点距离目标中点最近
    CGFloat minDelta = MAXFLOAT;
    for (UICollectionViewLayoutAttributes *attrs in layoutAttrsArr) {
        if (ABS(minDelta) > ABS(attrs.center.x - centerX)) {
            minDelta = attrs.center.x - centerX;
        }
    }
    
    // 修改原有的偏移量
    targetContentOffset->x += minDelta;
}


#pragma mark - 内部方法
/**
 item对应的默认位置
 
 @param item item的位置
 @return item对应的默认位置
 */
- (CGFloat)defaultPositionXWithItem:(NSInteger)item {
    return [self defaultPositionXWithIndex:item % self.numberOfItems];
}

/**
 item对应的默认位置
 
 @param index item对应的索引
 @return item对应的默认位置
 */
- (CGFloat)defaultPositionXWithIndex:(NSInteger)index {
    UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
    return layout.sectionInset.left + [self defaultItemAtIndex:index] * (layout.itemSize.width + layout.minimumLineSpacing);
}

/**
 默认索引
 
 @param index item对应的索引
 @return 默认索引
 */
- (NSInteger)defaultItemAtIndex:(NSInteger)index {
    return self.numberOfItems * kMultiple * 0.5 + index;
}

/**
 indexPath对应的实际index

 @param indexPath 虚拟位置
 @return 实际index
 */
- (NSInteger)indexAtItemPath:(NSIndexPath *)indexPath {
    return indexPath.item % self.numberOfItems;
}

/**
 滚动到默认位置
 */
- (void)scrollToDefaultPosition {
    [self scrollToItemAtIndex:0 animated:NO];
}

/**
 滚动到默认
 
 @param index item对应的索引
 @param animated 是否动画
 */
- (void)scrollToItemAtIndex:(NSInteger)index animated:(BOOL)animated {
    [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:[self defaultItemAtIndex:index] inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
}

@end
